using System;
using System.Collections.Generic;
using Bin;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using USBLiNK;
using ZedGraph;
using EngMATLib;
using Exocortex.DSP;
using System.IO;

namespace com.alexegg
{
    public partial class Form1 : Form
    {
        internal EngMATAccess ema;
        internal CSQuickUsb usb;
        MATLABFileIO fio;
        LineItem myCurve;
        LineItem myFFT;
        GraphPane RAWUSBPane;
        GraphPane FFTPane;
        MasterPane myMaster;
        PictureBox[] leds;

        public Form1()
        {
            InitializeComponent();

            usb = new CSQuickUsb();
            usb.USBConnectionChanged += new CSQuickUsb.usbEventHandler(OnUSBConnectionChanged);
            usbStatusStrip.Text = "USB Status: Disconnected";
            
           
        }

        private void Form1_Load(object sender, EventArgs e)
        {
            try
            {
                ema = new EngMATAccess();

                //TEMP SETTINGS
                ema.Evaluate("fs=1400"); //FOR BEN'S FUNCTION
                ema.Evaluate("cd work"); //FOR MAT LAB 7.0.1
                ///
            }
            catch (DllNotFoundException)
            {

                Log("MATLAB not loaded");
            }

            fio = new MATLABFileIO(this);
            
            if (!usb.Open(usb.FindDevices()))
            {
                MessageBox.Show(usb.LastError,"USB Connection Error",MessageBoxButtons.OK,MessageBoxIcon.Error);
                SetUSBControlsState(false);

               
            }

            if (usb.IsOpen)
            {
                //usbStatusStrip.Text = "USB Statue: Disconnect";
                WriteUSBSettings();
            }

            #region setup the graph

            myMaster = Graph.MasterPane;

            // Remove the default pane that comes with the ZedGraphControl.MasterPane
            myMaster.PaneList.Clear();
            myMaster.IsShowTitle = false;
            //Fill the pane background with a color gradient
            myMaster.PaneFill = new Fill(Color.FromArgb(((System.Byte)(159)), ((System.Byte)(191)), ((System.Byte)(245))), Color.FromArgb(((System.Byte)(196)), System.Drawing.Color.FromArgb(((System.Byte)(223)), ((System.Byte)(234)), ((System.Byte)(251)))));
            //Set the margins and the space between panes to 10 points
            myMaster.MarginAll = 10;
            myMaster.InnerPaneGap = 10;
            myMaster.Legend.IsVisible = false;

            RAWUSBPane = new GraphPane();
            RAWUSBPane.XAxis.Max = 512;
            RAWUSBPane.XAxis.IsShowGrid = true;
            RAWUSBPane.XAxis.ScaleFontSpec.FontColor = Color.Black;
            RAWUSBPane.XAxis.ScaleFontSpec.Size = 12;
            RAWUSBPane.XAxis.Step = 50;
           
            
            RAWUSBPane.YAxis.Max = 256;
            RAWUSBPane.YAxis.IsShowGrid = true;
            RAWUSBPane.YAxis.ScaleFontSpec.FontColor = Color.Black;
            RAWUSBPane.YAxis.ScaleFontSpec.Size = 12;
            RAWUSBPane.YAxis.Step = 50;


            //add a place holder line
            RAWUSBPane.AddCurve("USB Input", new double[1], new double[1], Color.Red, SymbolType.None);

            



            FFTPane = new GraphPane();
            FFTPane.XAxis.Max = 512;
            FFTPane.XAxis.IsShowGrid = true;
            FFTPane.XAxis.ScaleFontSpec.FontColor = Color.Black;
            FFTPane.XAxis.ScaleFontSpec.Size = 12;
            FFTPane.XAxis.Step = 50;

            FFTPane.YAxis.Max = 256;
            FFTPane.YAxis.IsShowGrid = true;
            FFTPane.YAxis.ScaleFontSpec.FontColor = Color.Black;
            FFTPane.YAxis.ScaleFontSpec.Size = 12;
            FFTPane.YAxis.Step = 50;

            FFTPane.AddCurve("FFT Output", new double[1], new double[1], Color.Blue, SymbolType.None);


           
            myMaster.Add(RAWUSBPane);
            myMaster.Add(FFTPane);



            // Tell ZedGraph to auto layout all the panes
            Graphics g = CreateGraphics();
            myMaster.AutoPaneLayout(g, PaneLayout.SingleColumn);
            myMaster.AxisChange(g);
            g.Dispose();

            /*
            myMaster = Graph.MasterPane;

            // Remove the default pane that comes with the ZedGraphControl.MasterPane
            myMaster.PaneList.Clear();
            myMaster.IsShowTitle = false;
            // Fill the pane background with a color gradient
            myMaster.PaneFill = new Fill(Color.FromArgb(((System.Byte)(159)), ((System.Byte)(191)), ((System.Byte)(245))), System.Drawing.Color.FromArgb(((System.Byte)(196)), System.Drawing.Color.FromArgb(((System.Byte)(223)), ((System.Byte)(234)), ((System.Byte)(251)))));
            // Set the margins and the space between panes to 10 points
            myMaster.MarginAll = 10;
            myMaster.InnerPaneGap = 10;
            myMaster.Legend.IsVisible = false;

            
            RAWUSBPane Graph Pane
            RAWUSBPane = new GraphPane();
            RAWUSBPane.XAxis.Max = 512;
            RAWUSBPane.YAxis.Max = 256;
            RAWUSBPane.XAxis.IsShowTitle = false;
            RAWUSBPane.YAxis.IsShowTitle = false;
            RAWUSBPane.FontSpec.Size = 20;
            RAWUSBPane.IsFontsScaled = false;
            RAWUSBPane.Legend.IsVisible = false;
            myMaster.Add(RAWUSBPane);

            RAWUSBPane = new GraphPane();

            myMaster.Add(RAWUSBPane);



            // FFT Graph Pane
            FFTPane = new GraphPane();
            FFTPane.XAxis.Max = 512;
            FFTPane.YAxis.Max = 256;
            FFTPane.XAxis.IsShowTitle = false;
            FFTPane.YAxis.IsShowTitle = false;
            FFTPane.FontSpec.Size = 10;
            FFTPane.IsFontsScaled = false;
            FFTPane.Legend.IsVisible = false;
            myMaster.Add(FFTPane);




            // Tell ZedGraph to auto layout all the panes
            Graphics g = CreateGraphics();
            myMaster.AutoPaneLayout(g, PaneLayout.SingleColumn);
            myMaster.AxisChange(g);
            g.Dispose();
*/
            #endregion


            leds = new PictureBox[8];
            leds[0] = led1;
            leds[1] = led2;
            leds[2] = led3;
            leds[3] = led4;
            leds[4] = led5;
            leds[5] = led6;
            leds[6] = led7;
            leds[7] = led8;
           
           
           
           
        }

        private void WriteUSBSettings()
        {
            //set settings 1 and 3


            if (usb.WriteSetting(1, 1))
            {
                //statusPanel1.Text = "setting 1 set to 16 bit mode";
            }
            else
                Log("error setting 1 to 16 bit mode");
            ///set 3


            if (usb.WriteSetting(3, 250))
            {
               // statusPanel1.Text = "setting 3 set to master mode";
            }
            else
               Log("error setting 3 set to master mode");

            
        }

        // Hook Events

        public void OnUSBConnectionChanged()
        {
            if (usb.IsOpen)
            {
                usbStatusStrip.Text = Properties.Resources.USBConnected;
                usbStatusStrip.Image = Properties.Resources.connect3;
                SetUSBControlsState(true);

                ///these are the quickusb settings for ben
                WriteUSBSettings();

            }
            else
            {
                usbStatusStrip.Text = Properties.Resources.USBDisconnected;
                Log("The connection to the USB port was closed");
                usbStatusStrip.Image = Properties.Resources.try7;
                SetUSBControlsState(false);
            }

        }

        private void SetUSBControlsState(bool enabled)
        {
           
         
            this.BeginInvoke((System.Threading.ThreadStart)delegate
            {
                if (!enabled)
                    checkBoxContFeed.Checked = enabled;


                checkBoxContFeed.Enabled = enabled;
                groupBoxAmps.Enabled = enabled;
                groupBoxSysStatus.Enabled = enabled;
                buttonWriteData.Enabled = enabled;
            });
           
        }


        private void Poll_ReadData()
        {

            if (checkBoxContFeed.Checked && !timerContFeed.Enabled)
            {
                timerContFeed.Start();
            }

            if (fio.GetAmpValuesFromUSB())
            {
                //upate those 3 bytes things
                labelRegister1.Text = fio.GraphPoints[2].ToString();
                labelRegister2.Text = fio.GraphPoints[3].ToString();
                labelRegister4.Text = fio.GraphPoints[4].ToString();

                //Update the Graph count
                statusPanelUSBStatus.Text = "  " + graphCounter.ToString() + " Samples";
                graphCounter++;

                //Clear The previous graphs
                myMaster.PaneList[0].CurveList.Clear();
                myMaster.PaneList[1].CurveList.Clear();

                //Add a new line to the Plot
                myCurve = RAWUSBPane.AddCurve("USB Input", null, Color.Red, SymbolType.None);

                //Create binary file for DYDA then run DYDA and copy image to clipboard
                MakeBowStaff(@"C:\BOWSTAFF2.cdf");
                if (ema != null && graphCounter==-2)
                {
                    if (ema.Evaluate("DYDA"))
                    {
                        
                       
                        // Declares an IDataObject to hold the data returned from the clipboard.
                        // Retrieves the data from the clipboard.
                        IDataObject iData = Clipboard.GetDataObject();

                        // Determines whether the data is in a format you can use.
                        if (iData.GetDataPresent(DataFormats.Bitmap))
                        {
                            // Yes it is, so display it in a text box.
                            pictureBoxMATLABPlot.Image = (Bitmap)iData.GetData(DataFormats.Bitmap);
                        }
                         
                         
                    }
                }

                PlotRegular();
                
                //PlotFFT();

                //Causes the graph to be redrawn
                Graph.Invalidate();

                DataBindLEDs(fio.USBprolog);

            }
            else
            {
                Log(usb.LastError);
                return;
            }
        }

        private void PlotRegular()
        {
            int x = 0;
            // Add points to plot
            foreach (byte point in fio.GraphPoints)
            {
                myCurve.AddPoint(x, point);
                x++;
            }
        }

        Bitmap on = Properties.Resources.onled;
        Bitmap off = Properties.Resources.off;
       
        private void DataBindLEDs(bool[]bitArray)
        {

            for (int i = 0; i < leds.Length; i++)
            {
                if (bitArray[i])
                {
                    leds[i].Image = on;
                }
                else
                {
                    leds[i].Image = off;
                }
            }
            
        }

        private void MakeBowStaff(string path)
        {
            FileStream fs = new FileStream(path, FileMode.Create);
            BinaryWriter bw = new BinaryWriter(fs);

            bw.Write(fio.GraphPoints);

            fs.Close();
            bw.Close();
        }


        private void PlotFFT()
        {
            myFFT = FFTPane.AddCurve("FFT Output", null, Color.FromKnownColor(KnownColor.MenuHighlight), SymbolType.None);
            float[] fft = new float[fio.GraphPoints.Length];
            fio.GraphPoints.CopyTo(fft, 0);
            
            Fourier.FFT(fft, 256, FourierDirection.Forward);

            
            for (int i = 0; i < fft.Length; i++)
            {
                fft[i] = 20*((float)Math.Log10((Math.Abs(fft[i]))));
            }

            int j = 0;
            foreach(float point in fft)
            {
                myFFT.AddPoint(j, point);
                j++;

            }

            Graph.Invalidate();
           
        }

        private void buttonVideo_Click(object sender, EventArgs e)
        {
            if ((string)buttonVideo.Tag == "Video Off")
            {
                this.buttonVideo.Image = com.alexegg.Properties.Resources.tool_normal;
                buttonVideo.BackColor = SystemColors.ActiveCaptionText;
                buttonVideo.Tag = "Video On";
               
            }
            else if ((string)buttonVideo.Tag == "Video On")
            {
                this.buttonVideo.Image = com.alexegg.Properties.Resources.tool_delay;
               buttonVideo.BackColor = SystemColors.ButtonFace;
               buttonVideo.Tag = "Video Off";
            }
              
        }

        private void ShowControlPanel(object sender, EventArgs e)
        {
            ControlPanel cp = new ControlPanel(ref usb);
            cp.Show();
        }

        private void buttonWriteData_Click(object sender, EventArgs e)
        {
            byte[] writeData;
            if (fio.ReadMATLABBinaryFile("C:\\MATLAB701\\WORK\\COEFFS", out writeData))
            {
                //Send data to usb
                if (usb.Write(writeData))
                {
                    //all is good in the hood
                }
                else
                {
                    Log("-ERR USB send error");
                   
                }

            }
            else
            {
                Log( "ERROR FROM buttonWriteData_Click()");
            }
        }

        #region amps
        private void trackBarAmp_Scroll(object sender, EventArgs e)
        {
            double y = 0;
            if (checkBoxHIGain1.Checked)
            {
                y = 1;
            }
            else if (!checkBoxHIGain1.Checked)
            {
                y = 0;
            }

            double result = (trackBarAmp.Value * .0557) * (1 + 6.079 * y);

            labelAmpValue1.Text = result.ToString("f");

            //SEND TO USB

            if (!SendAmpSettings())
            {
                statusPanelInfo.Text = usb.LastError;
            }

        }

        private void trackBarAmp2_Scroll(object sender, EventArgs e)
        {
            double y = 0;
            if (checkBoxHIGain2.Checked)
            {
                y = 1;
            }
            else if (!checkBoxHIGain2.Checked)
            {
                y = 0;
            }

            //double result = (y * 128) + trackBarAmp2.Value;
           double result = (trackBarAmp2.Value * .0557) * (1 + 6.079 * y);

            labelAmpValue2.Text = result.ToString("f");

            //SEND TO USB

            if (!SendAmpSettings())
            {
                Log(usb.LastError);
            }
        }

        private void trackBarAmp3_Scroll(object sender, EventArgs e)
        {
            double y = 0;
            if (checkBoxHIGain3.Checked)
            {
                y = 1;
            }
            else if (!checkBoxHIGain3.Checked)
            {
                y = 0;
            }

            double result = (trackBarAmp3.Value * .0557) * (1 + 6.079 * y);
            //double result = (y * 128) + trackBarAmp3.Value;

            labelAmpValue3.Text = result.ToString("f");

            //SEND TO USB

            if (!SendAmpSettings())
            {
                Log(usb.LastError);
            }

        }

        private void trackBarAmp4_Scroll(object sender, EventArgs e)
        {
            //double result = (this.trackBarAmp4.Value * 360) / 255;

            //this.labelAmpValue4.Text = result.ToString();

            //SEND TO USB

            if (!SendAmpSettings())
            {
                Log(usb.LastError);
            }

        }

        private void checkBoxHIGain1_CheckedChanged(object sender, EventArgs e)
        {
            if (checkBoxHIGain1.Checked)
            {
                double t = (trackBarAmp.Value * .0557) * (1 + 6.079 * 1);
                labelAmpValue1.Text = t.ToString("f");
            }
            else if (!checkBoxHIGain1.Checked)
            {
                double t = (trackBarAmp.Value * .0557) * (1 + 6.079 * 0);
                labelAmpValue1.Text = t.ToString("f");
            }

            //SEND TO USB

            if (!SendAmpSettings())
            {
                Log(usb.LastError);
            }

        }

        private void checkBoxHIGain2_CheckedChanged(object sender, EventArgs e)
        {
            if (checkBoxHIGain2.Checked)
            {
                double t = (trackBarAmp2.Value * .0557) * (1 + 6.079 * 1);
                labelAmpValue2.Text = t.ToString("f");
            }
            else if (!checkBoxHIGain2.Checked)
            {
                double t = (trackBarAmp2.Value * .0557) * (1 + 6.079 * 0);
                labelAmpValue2.Text = t.ToString("f");
            }

            //SEND TO USB

            if (!SendAmpSettings())
            {
                Log( usb.LastError);
            }


        }

        private void checkBoxHIGain3_CheckedChanged(object sender, EventArgs e)
        {
            if (checkBoxHIGain3.Checked)
            {
                double t = (trackBarAmp3.Value * .0557) * (1 + 6.079 * 1);
                labelAmpValue3.Text = t.ToString("f");
            }
            else if (!checkBoxHIGain3.Checked)
            {
                double t = (trackBarAmp3.Value * .0557) * (1 + 6.079 * 0);
                labelAmpValue3.Text = t.ToString("f");
            }

            //SEND TO USB

            if (!SendAmpSettings())
            {
                Log( usb.LastError);
            }

        }

        private byte amp4;
        private void checkBoxBit_CheckedChanged(object sender, EventArgs e)
        {
            StringBuilder sb = new StringBuilder(8);

            sb.Append(Convert.ToInt32(checkBoxBit0.Checked).ToString());
            sb.Append(Convert.ToInt32(checkBoxBit1.Checked).ToString());
            sb.Append(Convert.ToInt32(checkBoxBit2.Checked).ToString());
            sb.Append(Convert.ToInt32(checkBoxBit3.Checked).ToString());
            sb.Append(Convert.ToInt32(checkBoxBit4.Checked).ToString());
            sb.Append(Convert.ToInt32(checkBoxBit5.Checked).ToString());
            sb.Append(Convert.ToInt32(checkBoxBit6.Checked).ToString());
            sb.Append(Convert.ToInt32(checkBoxBit7.Checked).ToString());

            labelAmpValue4.Text = sb.ToString();

            amp4 = Convert.ToByte(Conversion.BinToUInt(sb.ToString()));
            labelAmpValue4DecimalVal.Text = amp4.ToString();

            //SEND TO USB

            if (!SendAmpSettings())
            {
                Log(usb.LastError);
            }
        }
        private bool SendAmpSettings()
        {
            byte[] ampSettings = new byte[4];

            if (checkBoxHIGain1.Checked)
                ampSettings[0] = Convert.ToByte(trackBarAmp.Value * 2);
            else
                ampSettings[0] = Convert.ToByte(trackBarAmp.Value);

            if (checkBoxHIGain2.Checked)
                ampSettings[1] = Convert.ToByte(trackBarAmp2.Value * 2);
            else
                ampSettings[1] = Convert.ToByte(trackBarAmp2.Value);

            if (checkBoxHIGain3.Checked)
                ampSettings[2] = Convert.ToByte(trackBarAmp3.Value * 2);
            else
                ampSettings[2] = Convert.ToByte(trackBarAmp3.Value);

            ampSettings[3] = amp4;


            //Write the data
            if (!usb.Write(ampSettings))
            {
                return false;

            }
            else
            {
                Log("Amplifier Settings Updated");
                return true;
            }

        }
        #endregion

        private void Form1_FormClosing(object sender, FormClosingEventArgs e)
        {
            usb.Close();
        }

        private void HookOfDeath(object sender, KeyEventArgs e)
        {
            if (e.Control && e.KeyCode == Keys.U)
            {
                //ControlPanel controlP = new ControlPanel(usb.Handle, ref usb);
                //controlP.Show();
            }
            else if (e.Control && e.KeyCode == Keys.S)
            {
                //SecretInputForm si = new SecretInputForm(this);
                //si.Show();

            }
            else if (e.Control && e.KeyCode == Keys.O)
            {
              //  Options o = new Options();
               // o.Show();

            }
        }

        private void timerClearStatusBar_Tick(object sender, EventArgs e)
        {
            statusPanelInfo.Text = String.Empty;

        }

        private void checkBoxContFeed_CheckedChanged(object sender, EventArgs e)
        {
            if (checkBoxContFeed.Checked && !timerContFeed.Enabled)
            {
                timerContFeed.Start();

                statusPanelInfo.Image = Properties.Resources.control_play_blue;
                

            }
            else if (timerContFeed.Enabled)
            {

            
                timerContFeed.Stop();
                statusPanelUSBStatus.Image = null;
                graphCounter = 0;

                
            }

        }

        int graphCounter;
        private void timerTick(object sender, EventArgs e)
        {
            if (checkBoxContFeed.Checked)
            {
                Poll_ReadData();
            }

        }

        private void buttonPlot_Click(object sender, EventArgs e)
        {
            throw new NotImplementedException("Ask Ben what to do with this");
            
        }

        private void toolStripMenuItemConnect_Click(object sender, EventArgs e)
        {
            if (!usb.Open(usb.FindDevices()))
            {
                Log("USB Connection could not be established: " + usb.LastError);
                SetUSBControlsState(false);
            }
        }

        private void toolStripMenuItemDisconnect_Click(object sender, EventArgs e)
        {
            usb.Close();
        }

        private void uSBControlPanelToolStripMenuItem_Click(object sender, EventArgs e)
        {
            ShowControlPanel(null, EventArgs.Empty);
        }

        private void timerStatusMessage_Tick(object sender, EventArgs e)
        {
            statusPanelInfo.Text = String.Empty;
           
        }

        internal void Log(string message)
        {
            timerStatusMessage.Stop();
            statusPanelInfo.Text = message;
            timerStatusMessage.Start();

        }



    }
}
